package com.dahua.messagesyncsh.service.Impl;

import com.alibaba.fastjson2.JSON;
import com.dahua.messagesyncsh.common.Constants;
import com.dahua.messagesyncsh.config.redis.RedisUtil;
import com.dahua.messagesyncsh.criteria.SensorDataQueryCriteria;
import com.dahua.messagesyncsh.entity.SensorData;
import com.dahua.messagesyncsh.entity.SensorDataAbbreviation;
import com.dahua.messagesyncsh.mapper.SensorDataMapper;
import com.dahua.messagesyncsh.pojo.CMode;
import com.dahua.messagesyncsh.pojo.Feature;
import com.dahua.messagesyncsh.pojo.Foundation;
import com.dahua.messagesyncsh.pojo.SyncData;
import com.dahua.messagesyncsh.service.SensorDataService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.List;

@Slf4j
@Service
public class SensorDataServiceImpl implements SensorDataService {
    @Resource
    private RedisUtil redisUtil;

    @Resource
    private SensorDataMapper sensorDataMapper;

    @Override
    public List<SensorDataAbbreviation> obtainAbbreviation(SensorDataQueryCriteria sensorDataQueryCriteria) {
        sensorDataQueryCriteria.setTableName(SensorDataQueryCriteria.prefix +
                sensorDataQueryCriteria.getEquipmentId() + "_" + sensorDataQueryCriteria.getSensorId());
        try{
            return sensorDataMapper.obtainAbbreviation(sensorDataQueryCriteria);
        }catch (Exception e){
            throw new RuntimeException(sensorDataQueryCriteria.getTableName() + " 查询失败 " +e.getMessage());
        }
    }

    @Override
    public Integer insert(SensorData sensorData) {
        if (!sensorData.verify()) {
            return 0;
        }
        sensorData.setTableName(SensorData.prefix + sensorData.getEqId() + "_" + sensorData.getSensorId());
        try {
            return sensorDataMapper.insert(sensorData);
        } catch (Exception e) {
            log.error("【SensorDataService】: {}插入更新失败 \n {}", sensorData.getTableName(), e.getMessage());
        }
        return 0;
    }

    @Override
    public Integer update(SensorData sensorData) {
        if (!sensorData.verify()) {
            return 0;
        }
        sensorData.setTableName(SensorData.prefix + sensorData.getEqId() + "_" + sensorData.getSensorId());

        try {
            return sensorDataMapper.update(sensorData);
        } catch (Exception e) {
            log.error("【SensorDataService】: {}数据更新失败 \n {}", sensorData.getTableName(), e.getMessage());
        }
        return 0;
    }

    public enum Type{
        CHART_FILE,
        FEATURE
    }

    public void toInsert(String key, Foundation foundation, SensorData sensorData, Type type) {
        /*  如果是返回null，
        * 如果返回全空对象，
        * 如果返回非空对象，
        * */
        Object hash = redisUtil.getHash(Constants.CMODE_FEATURE_SYNC, key);
        SyncData syncData = null;

        boolean isInsert = false;
        boolean isnNew = true;

        if (hash == null){
            boolean isOverOneHour = false;
            long boundary = System.currentTimeMillis() - (30 * 60 * 1000L);
            if (boundary >= foundation.getStartTime()) {
                isOverOneHour = true;
            }

            //  滞后半小时的数据
            if (isOverOneHour) {
                List<SensorDataAbbreviation> abbreviations = this.obtainAbbreviation(SensorDataQueryCriteria.builder()
                        .equipmentId(sensorData.getEqId())
                        .stationId(sensorData.getStationId())
                        .sensorId(sensorData.getSensorId())
                        .time(sensorData.getTime())
                        .build()
                );
                if (abbreviations == null || abbreviations.isEmpty()) {
                    isInsert = true;
                } else if (abbreviations.size() == 1) {
                    SensorDataAbbreviation abbreviation = abbreviations.get(0);
                    try{
                        boolean collision = abbreviation.isCollision(sensorData.toAbbreviation(), type);
                        if (collision) {
                            throw new RuntimeException("同时间点的数据冲突 " + sensorData.toLogString());
                        }
                    }catch (Exception e){
                        throw new RuntimeException("同时间点的数据冲突 " + sensorData.toLogString() + " " + e.getMessage());
                    }


                }else{
                    throw new RuntimeException("查询到多条同时间点的数据 \n" + sensorData.toLogString());
                }
            }
            //  非滞后数据且为insert数据
            else{
                // 如果对方重复发，还是无法保证唯一，但是避免重复查表和保证redis的大小不过大，暂先不考虑该种情况
                syncData = SyncData.builder()
                        .equipmentId(foundation.getEquipmentId())
                        .sensorId(foundation.getSensorId())
                        .startTime(foundation.getStartTime())
                        .isCMode(Boolean.FALSE)
                        .isFeature(Boolean.FALSE)
                        .isRms(Boolean.FALSE)
                        .isARms(Boolean.FALSE)
                        .build();
                if (foundation instanceof Feature){
                    syncData.setIsFeature(true);
                }
                if (foundation instanceof CMode){
                    syncData.setIsCMode(true);
                }
                isInsert = true;
            }
        }
        //  非滞后数据且为update数据
        else{
            try{
                syncData = JSON.parseObject(JSON.toJSONString(hash), SyncData.class);
            }catch (Exception e){
                throw new RuntimeException(e.getMessage());
            }
            //  博华的扶梯分rms和arms，同为feature，不用判断是否已经插入过
            if (foundation instanceof CMode  && syncData.getIsCMode()) {
                throw new RuntimeException("同时间点已有数据 \n" + sensorData.toLogString());
            }

            if (foundation instanceof Feature){
                syncData.setIsFeature(true);
            }
            if (foundation instanceof CMode){
                syncData.setIsCMode(true);
                isnNew = false;
            }
        }

        try{
            if (isInsert) {
                Integer insert = this.insert(sensorData);

            } else {
                Integer update = this.update(sensorData);
            }

            if (isnNew){
                //  插入后，保留标记
                redisUtil.setHash(Constants.CMODE_FEATURE_SYNC, key, syncData);
            }else{
                //  完成后清理标记
                redisUtil.deleteHash(Constants.CMODE_FEATURE_SYNC, key);
            }
        }catch (Exception e){
            throw new RuntimeException(e.getMessage());
        }
    }
}
